/**
 * Created by JustinChow on 2016/11/7.
 */

"use strict";

var Rectangle = require("../Utils/Rectangle");
var Vector = require("../Utils/Vector");

/**
 * !!!! WARNING !!!!
 *
 * When Base Class Include Classes That Extends From The Base Class,
 * Such As Player And Props Which Are Extends From The GameObject,
 * Then GameObject Will Become An Object And Never Be An Function,
 * So, After This, When We Init Player Or Props With GameObject.call() Or GameObject.apply() In The constructor,
 * Error Occurs.
 *
 * !!!! WARNING !!!!
 */
// var Player = require("./PlayerClass");
// var Props = require("./PropsClass");

/**
 * Collision Class
 * @type {Collision}
 */
var Collision = require("./CollisionClass");

/**
 * The Base Of All Game Objects
 *
 * @param {Number} objectId Through Function GameObject.getNewObjectId()
 * @param {PlayerTracker} owner
 * @param {Vector} position
 * @param {GameServer} gameServer
 */
function GameObject(objectId, owner, position, gameServer) {
    this.objectId = objectId;
    this.owner = owner; // PlayerTracker
    this.updateTime = new Date();

    this.type = -1;

    this.position = new Vector();
    if (position) this.position = new Vector(position.x, position.y);

    this.killedBy = null;
    this.gameServer = gameServer;

    this.moveEngine = new Vector();

    this.staticConfig = {};

    this.collision = new Collision();
    this.collisionRestoreTicks = 0;
}

module.exports = GameObject;

// Const Data

const TYPE_PLAYER = 0;
const TYPE_PROPS = 1;
const TYPE_BLOCK = 2;
const TYPE_DROP = 3;

GameObject.TYPE_PLAYER = TYPE_PLAYER;
GameObject.TYPE_PROPS = TYPE_PROPS;
GameObject.TYPE_BLOCK = TYPE_BLOCK;
GameObject.TYPE_DROP = TYPE_DROP;

// Getter And Setter

GameObject.prototype.getPosition = function () {
    return this.position;
};
GameObject.prototype.setPosition = function (x, y) {
    if (x instanceof Vector) {
        this.position.x = x.x;
        this.position.y = x.y;
    } else {
        this.position.x = x;
        this.position.y = y;
    }
};

GameObject.prototype.getKiller = function () {
    return this.killedBy;
};
GameObject.prototype.setKiller = function (obj) {
    if (obj.spellCaster) {
        this.killedBy = obj.spellCaster;
    } else {
        this.killedBy = player;
    }
    // if (obj instanceof Player) {
    //     this.killedBy = player;
    // } else if (obj instanceof Props) {
    //     this.killedBy = obj.spellCaster;
    // }
};

GameObject.prototype.getRange = function () {
    var height = 0;
    var width = 0;

    if (this.collision.boxType === Collision.BOX_TYPE_CIRCLE) {
        // height = width = this.collision.boxSize;
        width = this.collision.boxSize.x;
        height = this.collision.boxSize.y;
    } else if (this.collision.boxType === Collision.BOX_TYPE_RECTANGLE) {
        width = this.collision.boxSize.x / 2;
        height = this.collision.boxSize.y / 2;
    }

    return new Rectangle(this.position.x, this.position.y, width, height);
};

GameObject.prototype.moveEngineTick = function () {
    if (!this.gameServer) return;
    this.position.sub(this.moveEngine.clone().scale(0.5));
    this.move();
};

/**
 * Need To Call This Function Manually At End Of Each SubClass Constructor
 */
GameObject.prototype.initCollision = function () {
    this.collision.init(this.staticConfig.boxType, this.staticConfig.boxSize, this.staticConfig.through);
};

// Implement For Override

/**
 * If Need To Update
 * @returns Need To Return Boolean
 */
GameObject.prototype.sendUpdate = function () {
    throw new Error("sendUpdate Function Of GameObject Need To Override!!!");
};

/**
 * Called When Game Object Is Added Into The Scene
 */
GameObject.prototype.onAdd = function () {
    throw new Error("onAdd Function Of GameObject Need To Override!!!");
};

/**
 * Called When Game Object Is Added Into The Scene
 *
 * Totally On The Country To Function onAdd
 */
GameObject.prototype.onRemove = function () {
    throw new Error("onRemove Function Of GameObject Need To Override!!!");
};

/**
 * Called In The Private Function moveEngineTick() Each Tick Time
 */
GameObject.prototype.move = function () {
    throw new Error("Move Function Of GameObject Need To Override!!!");
};

/**
 * Load Static Config
 */
GameObject.prototype.loadConfig = function () {
    throw new Error("loadConfig Function Of GameObject Need To Override!!!");
};